
// #include "mq_exchange.hpp"
// #include "mq"
// #include <gtest/gtest.h>

// /////////////////////////////////////////////////
// /////////////////////////////////////////////////
// //////////////////////////////////// 对交换机的测试
// // chenmq::ExchangeManager::ptr emp;

// // class ExchangeTest:public testing::Environment
// // {
// // public:
// //     virtual void SetUp() override
// //     {
// //        // std::cout << "初始化数据" << std::endl;
// //         emp = std::make_shared<chenmq::ExchangeManager>("./data/meta.db");
// //     }

// //     virtual void TearDown() override
// //     {
// //         emp->clear();
// //        // std::cout << "清理数据" << std::endl;
// //     }
// // };

// // TEST(exchange_test, test_insert)
// // {
// //     // 交换机的属性
// //     std::unordered_map<std::string, std::string> map1 = {{"key1", "val1"}, {"key2", "val2"}};
// //     emp->declareExchange("exchange1", chenmq::ExchangeType::DIRECT, true, false, map1);
// //     emp->declareExchange("exchange2", chenmq::ExchangeType::DIRECT, true, false, map1);
// //     emp->declareExchange("exchange3", chenmq::ExchangeType::DIRECT, true, false, map1);
// //     emp->declareExchange("exchange4", chenmq::ExchangeType::DIRECT, true, false, map1);
// //     emp->declareExchange("exchange5", chenmq::ExchangeType::DIRECT, true, false, map1);
// //     ASSERT_EQ(emp->size(), 5);
// // }

// // TEST(exchange_test, test_select)
// // {
// //     ASSERT_EQ(emp->exists("exchange1"), true);
// //     ASSERT_EQ(emp->exists("exchange2"), true);
// //     ASSERT_EQ(emp->exists("exchange3"), true);
// //     ASSERT_EQ(emp->exists("exchange4"), true);
// //     //ASSERT_EQ(emp->exists("exchange6"), true);
// //     chenmq::Exchange::ptr exp = emp->selectExchange("exchange2");

// // }

// // int main(int argc, char* argv[])
// // {
// //     testing::InitGoogleTest(&argc, argv);
// //     testing::AddGlobalTestEnvironment(new ExchangeTest);
// //     return RUN_ALL_TESTS();
// //     //return 0;
// // }

// /////////////////////////////////////////////////
// /////////////////////////////////////////////////
// //////////////////////////////////// 对交换机的测试

// // #include <iostream>
// // #include <string>
// // #include <functional>
// // #include <vector>
// // #include <unistd.h>
// // #include <stdlib.h>
// // #include <signal.h>
// // #include <sys/wait.h>

// // void PrintPending(const sigset_t &pending)
// // {
// //     std::cout << "curr pending list [" << getpid() << "]: " ;
// //     for(int signo = 31; signo > 0; signo--)
// //     {
// //         if(sigismember(&pending, signo))
// //         {
// //             std::cout << 1;
// //         }
// //         else
// //         {
// //             std::cout << 0;
// //         }
// //     }
// //     std::cout << std::endl;
// // }
// // void non_handler(int signo)
// // {
// //     std::cout << "处理:" << signo << std::endl;
// // }

// // int main()
// // {
// //     ::signal(2, SIG_IGN);
// //     // ::signal(2, non_handler);
// //     // 1. 对2号信号进行屏蔽
// //     // 栈上开辟的空间
// //     sigset_t block, oblock;
// //     sigemptyset(&block);
// //     sigemptyset(&oblock);
// //     // 1.1 添加2号信号
// //     // 我们有没有把对2号信号的屏蔽，设置进入内核中？只是在用户栈上设置了block的位图结构
// //     // 并没有设置进入内核中！
// //     sigaddset(&block, 2);
// //     // 1.2 设置进入内核中
// //     sigprocmask(SIG_SETMASK, &block, &oblock);

// //     int cnt = 0;

// //     while(true)
// //     {
// //         // 2. 如何获取pending表呢？
// //         sigset_t pending;
// //         sigpending(&pending);

// //         // 2.1 打印
// //         PrintPending(pending);

// //         sleep(1);

// //         cnt++;

// //         if(cnt == 10)
// //         {
// //             std::cout << "解除对2号信号的屏蔽" << std::endl;
// //             sigprocmask(SIG_SETMASK, &oblock, nullptr);
// //         }
// //     }

// //     return 0;
// // }

// #include "mq_binding.hpp"

// chenmq::BindingManager::ptr bmp;

// class QueueTest : public testing::Environment {
//     public:
//         virtual void SetUp() override {
//             bmp = std::make_shared<chenmq::BindingManager>("./data/meta.db");
//         }
//         virtual void TearDown() override {
//             //bmp->clear();
//         }
// };
// TEST(queue_test, insert_test) {
//     bmp->bind("exchange1", "queue1", "news.music.#", true);
//     bmp->bind("exchange1", "queue2", "news.sport.#", true);
//     bmp->bind("exchange1", "queue3", "news.gossip.#", true);
//     bmp->bind("exchange2", "queue1", "news.music.pop", true);
//     bmp->bind("exchange2", "queue2", "news.sport.football", true);
//     bmp->bind("exchange2", "queue3", "news.gossip.#", true);
//     ASSERT_EQ(bmp->size(), 6);
// }

// TEST(queue_test, recovery_test)
// {
//     ASSERT_EQ(bmp->exists("exchange1", "queue1"), true);
//     ASSERT_EQ(bmp->exists("exchange1", "queue2"), true);
//     ASSERT_EQ(bmp->exists("exchange1", "queue3"), true);
//     ASSERT_EQ(bmp->exists("exchange2", "queue1"), true);
//     ASSERT_EQ(bmp->exists("exchange2", "queue2"), true);
//     ASSERT_EQ(bmp->exists("exchange2", "queue3"), true);
// }

// // TEST(queue_test, insert_test) {
// //     bmp->bind("exchange1", "queue1", "news.music.#", true);
// //     bmp->bind("exchange1", "queue2", "news.sport.#", true);
// //     bmp->bind("exchange1", "queue3", "news.gossip.#", true);
// //     bmp->bind("exchange2", "queue1", "news.music.pop", true);
// //     bmp->bind("exchange2", "queue2", "news.sport.football", true);
// //     bmp->bind("exchange2", "queue3", "news.gossip.#", true);
// //     ASSERT_EQ(bmp->size(), 6);
// // }

// // TEST(queue_test, select_test) {
// //     ASSERT_EQ(bmp->exists("exchange1", "queue1"), true);
// //     ASSERT_EQ(bmp->exists("exchange1", "queue2"), true);
// //     ASSERT_EQ(bmp->exists("exchange1", "queue3"), true);
// //     ASSERT_EQ(bmp->exists("exchange2", "queue1"), true);
// //     ASSERT_EQ(bmp->exists("exchange2", "queue2"), true);
// //     ASSERT_EQ(bmp->exists("exchange2", "queue3"), true);

// //     bitmq::Binding::ptr bp = bmp->getBinding("exchange1", "queue1");
// //     ASSERT_NE(bp.get(), nullptr);
// //     ASSERT_EQ(bp->exchange_name, std::string("exchange1"));
// //     ASSERT_EQ(bp->msgqueue_name, std::string("queue1"));
// //     ASSERT_EQ(bp->binding_key, std::string("news.music.#"));
// // }

// // TEST(queue_test, select_exchange_test) {
// //     bitmq::MsgQueueBindingMap mqbm = bmp->getExchangeBindings("exchange1");
// //     ASSERT_EQ(mqbm.size(), 3);
// //     ASSERT_NE(mqbm.find("queue1"), mqbm.end());
// //     ASSERT_NE(mqbm.find("queue2"), mqbm.end());
// //     ASSERT_NE(mqbm.find("queue3"), mqbm.end());
// // }

// // // e2-q3

// // TEST(queue_test, remove_queue_test) {
// //     bmp->removeMsgQueueBindings("queue1");
// //     ASSERT_EQ(bmp->exists("exchange1", "queue1"), false);
// //     ASSERT_EQ(bmp->exists("exchange2", "queue1"), false);
// // }

// // TEST(queue_test, remove_exchange_test) {
// //     bmp->removeExchangeBindings("exchange1");
// //     ASSERT_EQ(bmp->exists("exchange1", "queue1"), false);
// //     ASSERT_EQ(bmp->exists("exchange1", "queue2"), false);
// //     ASSERT_EQ(bmp->exists("exchange1", "queue3"), false);
// // }

// // TEST(queue_test, remove_single_test) {
// //     ASSERT_EQ(bmp->exists("exchange2", "queue2"), true);
// //     bmp->unBind("exchange2", "queue2");
// //     ASSERT_EQ(bmp->exists("exchange2", "queue2"), false);
// //     ASSERT_EQ(bmp->exists("exchange2", "queue3"), true);
// // }

// int main(int argc,char *argv[])
// {
//     testing::InitGoogleTest(&argc, argv);
//     testing::AddGlobalTestEnvironment(new QueueTest);
//     RUN_ALL_TESTS();
//     return 0;
// }

#include "mq_binding.hpp"
#include "mq_exchange.hpp"
#include "mq_message.hpp"
#include "mq_queue.hpp"
#include "mq_host.hpp"
#include <gtest/gtest.h>

// chenmq::MessageManager::ptr mmq;
// class MessageTest: public testing::Environment
// {
//     public:
//         virtual void SetUp() override
//         {
//             mmq = std::make_shared<chenmq::MessageManager>("./data/message");
//             mmq->initQueueMessage("queue1"); //这里初始化的队列，就是咱们虚拟机中的队列
//         }

//         virtual void TearDown() override
//         {
//             mmq->clear();
//         }
// };

// TEST(message_test, insert_test)
// {
//     chenmq::BasicProperties properties;
//     properties.set_id(chenmq::UUIDHelper::uuid());
//     properties.set_delivery_mode(chenmq::DeliveryMode::DURABLE);
//     properties.set_routing_key("news.music.pop");
//     mmq->insert("queue1", &properties, "hello-world-1", chenmq::DeliveryMode::DURABLE);
//     mmq->insert("queue1", nullptr, "hello-world-2", chenmq::DeliveryMode::DURABLE);
//     mmq->insert("queue1", nullptr, "hello-world-3", chenmq::DeliveryMode::DURABLE);
//     mmq->insert("queue1", nullptr, "hello-world-4", chenmq::DeliveryMode::DURABLE);
//     mmq->insert("queue1", nullptr, "hello-world-5", chenmq::DeliveryMode::UNDURABLE);
//     ASSERT_EQ(mmq->getable_count("queue1"), 5);
//     //ASSERT_EQ(mmq->total_count("queue1"), 4);
//     ASSERT_EQ(mmq->durable_count("queue1"), 4);
//     ASSERT_EQ(mmq->waitack_count("queue1"), 0);
// }

// int main(int argc, char* argv[])
// {
//      testing::InitGoogleTest(&argc, argv);
//     testing::AddGlobalTestEnvironment(new MessageTest);
//     //testing::AddGlobalTestEnvironment(new MessageTest2);
//     RUN_ALL_TESTS();
//     return 0;
// }

class HostTest : public testing::Test
{
public:
    void SetUp() override
    {
        std::unordered_map<std::string, std::string> empty_map;
        _host = std::make_shared<chenmq::VirtualHost>("host1", "./data/host1/message/", "./data/host1/host1.db");
        _host->declareExchange("exchange1", chenmq::ExchangeType::DIRECT, true, false, empty_map);
        _host->declareExchange("exchange2", chenmq::ExchangeType::DIRECT, true, false, empty_map);
        _host->declareExchange("exchange3", chenmq::ExchangeType::DIRECT, true, false, empty_map);

        _host->declareQueue("queue1", true, false, false, empty_map);
        _host->declareQueue("queue2", true, false, false, empty_map);
        _host->declareQueue("queue3", true, false, false, empty_map);

        _host->Bind("exchange1", "queue1", "news.music.#");
        _host->Bind("exchange1", "queue2", "news.music.#");
        _host->Bind("exchange1", "queue3", "news.music.#");

        _host->Bind("exchange2", "queue1", "news.music.#");
        _host->Bind("exchange2", "queue2", "news.music.#");
        _host->Bind("exchange2", "queue3", "news.music.#");

        _host->Bind("exchange3", "queue1", "news.music.#");
        _host->Bind("exchange3", "queue2", "news.music.#");
        _host->Bind("exchange3", "queue3", "news.music.#");

        _host->basicPublish("queue1", nullptr, "helloword-1");
        _host->basicPublish("queue1", nullptr, "helloword-2");
        _host->basicPublish("queue1", nullptr, "helloword-3");

        _host->basicPublish("queue2", nullptr, "helloword-1");
        _host->basicPublish("queue2", nullptr, "helloword-2");
        _host->basicPublish("queue2", nullptr, "helloword-3");

        _host->basicPublish("queue3", nullptr, "helloword-1");
        _host->basicPublish("queue3", nullptr, "helloword-2");
        _host->basicPublish("queue3", nullptr, "helloword-3");

        DLOG("资源初始化完毕");
    }

    void TearDown() override
    {
        _host->clear();
        DLOG("资源清理完毕");
    }

public:
    chenmq::VirtualHost::ptr _host;
};

TEST_F(HostTest, init_test)
{
    ASSERT_EQ(_host->existsExchange("exchange1"), true);
    ASSERT_EQ(_host->existsExchange("exchange2"), true);
    ASSERT_EQ(_host->existsExchange("exchange3"), true);

    ASSERT_EQ(_host->existsQueue("queue1"), true);
    ASSERT_EQ(_host->existsQueue("queue2"), true);
    ASSERT_EQ(_host->existsQueue("queue3"), true);

    ASSERT_EQ(_host->existsBinding("exchange1", "queue1"), true);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue2"), true);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue3"), true);

    ASSERT_EQ(_host->existsBinding("exchange2", "queue1"), true);
    ASSERT_EQ(_host->existsBinding("exchange2", "queue2"), true);
    ASSERT_EQ(_host->existsBinding("exchange2", "queue3"), true);

    ASSERT_EQ(_host->existsBinding("exchange3", "queue1"), true);
    ASSERT_EQ(_host->existsBinding("exchange3", "queue2"), true);
    ASSERT_EQ(_host->existsBinding("exchange3", "queue3"), true);

    chenmq::MessagePtr msg1 = _host->basicConsume("queue1");
    ASSERT_EQ(msg1->payload().body(), std::string("helloword-1"));
    chenmq::MessagePtr msg2 = _host->basicConsume("queue1");
    ASSERT_EQ(msg2->payload().body(), std::string("helloword-2"));
    chenmq::MessagePtr msg3 = _host->basicConsume("queue1");
    ASSERT_EQ(msg3->payload().body(), std::string("helloword-3"));
    chenmq::MessagePtr msg4 = _host->basicConsume("queue1");
    ASSERT_EQ(msg4.get(), nullptr);
}

TEST_F(HostTest, remove_exchange)
{
    _host->deleteExchange("exchange1");
    ASSERT_EQ(_host->existsBinding("exchange1", "queue1"), false);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue2"), false);
    ASSERT_EQ(_host->existsBinding("exchange1", "queue3"), false);
}

TEST_F(HostTest, remove_queue)
{
    _host->deleteQueue("queue1");
    ASSERT_EQ(_host->existsBinding("exchange1", "queue1"), false);
    ASSERT_EQ(_host->existsBinding("exchange2", "queue1"), false);
    ASSERT_EQ(_host->existsBinding("exchange3", "queue1"), false);

    chenmq::MessagePtr msg1 = _host->basicConsume("queue1");
    ASSERT_EQ(msg1.get(), nullptr);
}

TEST_F(HostTest, ack_message)
{
    chenmq::MessagePtr msg1 = _host->basicConsume("queue1");
    ASSERT_EQ(msg1->payload().body(), std::string("helloword-1"));
    _host->basicAck(std::string("queue1"), msg1->payload().properties().id());

    chenmq::MessagePtr msg2 = _host->basicConsume("queue1");
    ASSERT_EQ(msg2->payload().body(), std::string("helloword-2"));
    _host->basicAck(std::string("queue1"), msg2->payload().properties().id());

    chenmq::MessagePtr msg3 = _host->basicConsume("queue1");
    ASSERT_EQ(msg3->payload().body(), std::string("helloword-3"));
    _host->basicAck(std::string("queue1"), msg3->payload().properties().id());
}

// int main(int argc, char* argv[])
// {
//     testing::InitGoogleTest(&argc, argv);
//     //testing::AddGlobalTestEnvironment(new MyTest);
//     return RUN_ALL_TESTS();
// }

// 交换机类型
// 广播交换: 将消息发布到所有绑定的队列中
// 直接交换: 用户发布消息的时候，消息中有一个routing_key，与那个队列的binding_key相同就匹配成功
// 主题交换: 按照匹配规则进行匹配

// 路由交换模块
//  功能： 判断一个消息中的routing_key与队列的binding_key是否匹配成功

// 信道管理模块
// 1,管理信息 ：信道ID, 信道关联的消费者。信道关联的连接
